﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using BootstrapBlazor.Components;
using BootstrapBlazor.Shared.Common;
using CodeManDesktopBlazor.BlazorComponents.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Microsoft.JSInterop;

using Microsoft.Extensions.Logging;
using CodeMan.Application.Contracts.ClassGens;
using System.Collections;
using CodeMan.ClassGens;
using CodeMan.Domain.Shared.Enums;
using Volo.Abp.ObjectMapping;

namespace CodeManDesktopBlazor.BlazorComponents.Pages
{
    /// <summary>
    /// 
    /// </summary>
    public partial class CodeGen : ComponentBase
    {
        #region Inject

        [Inject]
        ILogger<CodeGen> Logger { get; set; }
        /// <summary>
        ///
        /// </summary>
        [Inject]
        private IJSRuntime JSRuntime { get; set; }
        [Inject]
        private ToastService ToastService { get; set; }

        private IClassGenAppService ClassGenAppService { get; set; }
        private IDataService<ClassAttributeDTO> ClassAttributeAppService { get; set; }
        private IOtherDBAppService OtherDBAppService { get; set; }
        private IObjectMapper ObjectMapper;
        #endregion

        #region params 
        /// <summary>
        /// 获得/设置 CodeGen 高度
        /// </summary>
        [Parameter] public int? Height { get; set; }
        [Parameter] public int? Width { get; set; }
        private bool isLoadDB { get; set; } = false;
        private string DbNameSpace { get; set; }

        public CodeManGenUI<ClassGenDTOCreateUpdate, ClassAttributeDTO> Model { get; set; } = new CodeManGenUI<ClassGenDTOCreateUpdate, ClassAttributeDTO>()
        {
            classGenDTO = new ClassGenDTOCreateUpdate()
            {
                Name = "a"
            },
            classAttributeDTOLst = new List<ClassAttributeDTO>()
            {
            }

        };
        /// <summary>
        /// 获得 wrapper 样式表集合
        /// </summary>
        protected string? FixedHeaderStyleName => CssBuilder.Default()
            .AddClass($"height: {Height}px;", Height.HasValue)
            .AddClass($"min-width: {Width}px;", Width.HasValue)
            .Build();

        /// <summary>
        /// 获得 默认数据集合
        /// </summary>
        private IEnumerable<SelectedItem> ClassTypeSelectList { get; set; } =
        Enumerable.Empty<SelectedItem>();

        private string codeContent { get; set; }

        private ElementReference PreElement { get; set; }
        private bool Loaded { get; set; }
        private bool CanCopy { get; set; }
        Dictionary<string, TreeItem> CacheTreeItem = new Dictionary<string, TreeItem>();
        ICollection<SelectedItem> CacheTreeItemSelect
        {
            get
            {
                return CacheTreeItem.Keys.Select(a => new SelectedItem() { Text = a, Value = a }).ToList();
            }
        }
        private string SearchText { get; set; }

        [NotNull]
        private Tab? TabSet { get; set; }

        [NotNull]
        private Toast? Toast { get; set; }
        [NotNull]
        private ToastOption? Options1 { get; set; }
        private bool copyIsDisabled { get; set; } = false;
        #endregion
        #region input cotent
        [Inject]
        [NotNull]
        private IStringLocalizer<ClassAttributeDTO>? Localizer { get; set; }
        private string? PlaceHolderText { get; set; }
        #endregion
        #region MarkDown
        /// <summary>
        /// 获得/设置 DOM 元素实例
        /// </summary>
        private Markdown MarkdownElement { get; set; }
        private string? MarkdownString { get; set; }

        private string? HtmlString { get; set; }
        private string? CopyToClipboardString { get; set; } = "复制代码";

        /// <summary>
        /// 获得/设置 版本号字符串
        /// </summary>
        private string Version { get; set; } = "fetching";

        private string? Language { get; set; }
        #endregion

        #region OnInitialized

        /// <summary>
        /// 
        /// </summary>
        protected override void OnInitialized()
        {
            base.OnInitialized();

            PlaceHolderText = Localizer["InputContent"];
            Options1 = new ToastOption { Title = "复制到本地", IsAutoHide = false, Content = "复制到本地数据成功，4 秒后自动关闭" };
        }
        /// <summary>
        /// 
        /// </summary>
        protected override async Task OnInitializedAsync()
        {
            //init service 
            ClassGenAppService = GData.currMainWindow.GetClassGenAppService();
            OtherDBAppService = GData.currMainWindow.GetOtherDBAppService();
            ObjectMapper = GData.currMainWindow.GetobjectMapper();
            ClassAttributeAppService = GData.currMainWindow.GetDataDetailsMainService();

            //int params
            Height = GData.mainjs.heightInt - 40;
            Width = GData.mainjs.widthInt - 10;

            //init markdonw
            Language = CultureInfo.CurrentUICulture.Name;
            MarkdownString = "### 测试";
            //Version = await VersionManager.GetVersionAsync("bootstrapblazor.markdown"); 

            await base.OnInitializedAsync();

            Loaded = true;
            CanCopy = true;


        }

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            await base.OnAfterRenderAsync(firstRender);

            //if (Loaded)
            //{
            //    await JSRuntime.InvokeVoidAsync("$.highlight", PreElement); 
            //}
            if (firstRender)
            {
                TabSet.ActiveTab(TabSet.Items.First());
            }

        }
        private List<Pet> pets = new()
        {
            new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
            new Pet { PetId = 4, Name = "Salem Saberhagen" },
            new Pet { PetId = 7, Name = "K-9" }
        };
        private List<string> attrs = new()
        {
        };
        #endregion
        #region 复制代码
        private Task OnSelectedItemChanged(SelectedItem item)
        {
            CopyToClipboardString = "复制代码";
            return Task.CompletedTask;
        }
        private async void OnSelectedSearchItemChanged(ChangeEventArgs e)
        {
            if (CacheTreeItem.Count <= 0)
            {
                foreach (var item in CheckedItems)
                {
                    await OnExpandNode(item);
                    item.ShowLoading = false;
                }
            }
            foreach (var item in CheckedItems)
            {
                item.IsExpanded = false;
                item.HasChildNode = true;
                item.Clear();
            }
            if (e.Value.NullToStr().IsNullOrWhiteSpace())
            {
                return;
            }

            var filters = CacheTreeItem.Where(a => a.Key.Substring(0, a.Key.Length - 2).Contains(e.Value?.ToString(), StringComparison.CurrentCultureIgnoreCase));
            foreach (var item in filters)
            {
                var indexExt = item.Key.Split('_').Last().TryToInt();
                CheckedItems[indexExt].AddItem(item.Value);
                CheckedItems[indexExt].IsExpanded = true;
            }
            await Task.CompletedTask;
        }
        private void GenCodeClick()
        {
            try
            {

                if (!Model.classAttributeDTOLst.HasItem())
                {
                    var allAtt = Model.InputContent.Split(",");
                    foreach (var item in allAtt)
                    {
                        Model.classAttributeDTOLst.Add(new ClassAttributeDTO() { AName = item });
                    }
                }
                CopyToClipboardString = "复制代码";

            }
            catch (Exception ex)
            {
                Logger?.LogError(ex, "GenCodeClick");
                MarkdownString = $"### {ex.Message}";
            }
        }


        private async Task CopyToClipboard(string divid)
        {
            try
            {
                var text = await JSRuntime.InvokeAsync<string>("$.getEltext", $"#{divid}");

                codeContent = text;

                Clipboard.SetDataObject(text, true);

                CopyToClipboardString = "已复制好，可贴粘";
                //StateHasChanged();
            }
            catch (Exception ex)
            {
                Logger?.LogError(ex, "CopyToClipboard");
                MarkdownString = ex.Message;
            }
        }

        #endregion

        #region 下边面板
        private async Task ReflashClick()
        {
            Model = new CodeManGenUI<ClassGenDTOCreateUpdate, ClassAttributeDTO>()
            {
                classGenDTO = new ClassGenDTOCreateUpdate()
                {
                    Name = "a"
                },
                classAttributeDTOLst = new List<ClassAttributeDTO>()
                {
                }

            };
            foreach (var item in CheckedItems)
            {
                item.HasChildNode = true;
                item.Clear();
            }
            //load data 
            //await GetTreeItemAsync(CheckedItems);
        }
        public async Task GenCopyClick()
        {

            Toast.SetPlacement(Placement.BottomEnd);
            if (Model.classGenDTO != null && Model.classAttributeDTOLst.HasItem())
            {
                var tosave = ObjectMapper.Map<ClassGenDTOCreateUpdate, ClassGenDTOCreateUpdate>
(Model.classGenDTO);
                tosave.Id = 0;
                var tosaveDetails = ObjectMapper.Map<List<ClassAttributeDTO>, List<ClassAttributeDTO>>(Model.classAttributeDTOLst);
                await ClassGenAppService.SaveClassAndAtt(tosave, tosaveDetails);

                await ToastService.Show(new ToastOption()
                {
                    Category = ToastCategory.Success,
                    Title = "复制到本地",
                    Content = $"{tosave.Name}:复制到本地数据成功，4 秒后自动关闭"
                });
            }
            else
            {
                await ToastService.Show(new ToastOption()
                {
                    Category = ToastCategory.Error,
                    Title = "复制到本地",
                    Content = $"请选择要复制的表/类，4 秒后自动关闭"
                });
            }
            await Task.CompletedTask;
        }
        private async Task OnTreeItemClick(TreeItem item)
        {
            Logger?.LogDebug($"TreeItem: {item.Text} clicked");
            try
            {
                if (item.Tag != null && !item.IsDisabled)
                {
                    Model.classGenDTO = item.Tag as ClassGenDTOCreateUpdate;
                    var listAttr = item.Items.Where(a => a.Items.Any())
                       .FirstOrDefault();

                    if (listAttr != null)
                    {
                        Model.classAttributeDTOLst = listAttr.Items.Select(a => a.Tag as ClassAttributeDTO).ToList();
                    }

                    Model.InputContent = Model.InputContentAtt;
                    //StateHasChanged();  
                }
            }
            catch (Exception ex)
            {
                Logger?.LogError(ex, "OnTreeItemClick");
            }
            await Task.CompletedTask;
        }
        private Task NameValueChanged(string v)
        {

            return Task.CompletedTask;
        }
        private Task OnTreeItemChecked(TreeItem item)
        {
            var state = item.Checked ? "选中" : "未选中";
            Logger?.LogDebug($"TreeItem: {item.Text} {state}");
            try
            {
                copyIsDisabled = false;
                if (item.Tag != null)
                {
                    Model.classGenDTO = item.Tag as ClassGenDTOCreateUpdate;

                    if (Model.classGenDTO?.FromType == FromTypeEnum.otherDB)
                    {
                        isLoadDB = true;
                        Model.classGenDTO.Namespace = DbNameSpace;
                    }
                    else
                    {
                        isLoadDB = false;
                    }
                }

                if (item.Checked)
                {

                    var listAttr = item.Items.Where(a => a.Items.Any())
                       .FirstOrDefault();

                    if (listAttr != null)
                    {
                        Model.classAttributeDTOLst = listAttr.Items.Select(a => a.Tag as ClassAttributeDTO).ToList();
                        copyIsDisabled = true;
                    }

                    Model.InputContent = Model.InputContentAtt;
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                Logger?.LogError(ex, "OnTreeItemChecked");
            }
            return Task.CompletedTask;
        }
        private void initClassTypeSelectList(ClassGenDTOCreateUpdate classGenDTO)
        {
            if (!ClassTypeSelectList.HasItem() && classGenDTO != null)
            {
                Type? innerType = classGenDTO.Type.GetType();
                if (typeof(IEnumerable).IsAssignableFrom(innerType))
                {
                    innerType = innerType.GetGenericArguments()[0];
                }
                if (innerType != null && innerType.IsEnum)
                {
                    ClassTypeSelectList = innerType.ToSelectList();
                }
            }
        }
        public async Task<IReadOnlyList<TreeItem>> GetTreeItemAsync(IReadOnlyList<TreeItem> treeItems, int index = 0, string key = "")
        {
            var treeItem = treeItems[index];
            IReadOnlyList<TreeItem> localData = new List<TreeItem>();
            switch (index)
            {
                case 0:
                    isLoadDB = false;
                    localData = await ClassGenAppService?.GetTreeItemsAsync(key.TryToInt64());
                    break;
                case 1:
                    isLoadDB = true;
                    localData = await OtherDBAppService?.GetTreeItemsAsync(key);
                    break;
            }
            if (key.IsNullOrWhiteSpace2())
            {
                foreach (var item in localData)
                {
                    treeItem.AddItem(item);
                    CacheTreeItem[$"{item.Text}_{index}"] = item;
                }
            }
            return localData;

        }
        private async Task OnExpandNode(TreeItem item)
        {
            try
            {
                var itemType = item.Key?.ToString().Split('_');
                if (!item.Items.HasItem() && item.HasChildNode && !item.ShowLoading)
                {
                    item.ShowLoading = true;
                    int tagindext = 0;
                    string tTablekey = "";
                    switch (itemType[0])
                    {
                        case "db":
                            var tag = item.Tag?.ToString();
                            tagindext = itemType[1].TryToInt();
                            break;
                        case "table":
                            tTablekey = itemType[1] == "0" ? itemType[2] : item.Text;
                            tagindext = itemType[1].TryToInt();
                            break;
                        default:
                            break;
                    }
                    await Task.Delay(800);
                    var getresult = await GetTreeItemAsync(CheckedItems, tagindext, tTablekey);
                    if (itemType[0] == "table")
                    {
                        item.Clear();
                        foreach (var itemD in getresult)
                        {
                            item.AddItem(itemD);
                        }
                    }
                    if (getresult.Count > 0)
                    {
                        item.HasChildNode = false;
                    }
                    item.ShowLoading = false;
                }

            }
            catch (Exception ex)
            {
                Logger?.LogError(ex, "OnExpandNode");
                item.ShowLoading = false;
            }
            finally
            {
                item.ShowLoading = false;
            }
        }

        private List<TreeItem> CheckedItems { get; set; } = new List<TreeItem>()
        {

                new TreeItem() { Text = "本地数据", HasChildNode = true , Key = "db_0", Tag=0, IsDisabled=true},
                new TreeItem() { Text = "数据库" , HasChildNode = true , Key = "db_1", Tag=1, IsDisabled=true}

        };

        #endregion
    }
}
